import { useState, useEffect, useCallback, useMemo } from 'react'
import { dictManager } from '../utils/dictManager'
import { DictData, DICT_TYPE } from '../api/dict'

/**
 * 字典Hook返回类型
 */
interface UseDictReturn {
    dictData: Record<string, DictData[]>
    loading: boolean
    error: string | null
    refresh: () => Promise<void>
    getDictOptions: (dictType: string) => Array<{ label: string; value: string | number }>
    getDictLabel: (dictType: string, value: string | number) => string
    getIntDictOptions: (dictType: string) => Array<{ label: string; value: number }>
    getStrDictOptions: (dictType: string) => Array<{ label: string; value: string }>
}

/**
 * 使用字典数据的Hook
 * @param dictTypes 需要获取的字典类型数组
 * @returns 字典数据和相关方法
 */
export const useDict = (dictTypes: string[]): UseDictReturn => {
    const [dictData, setDictData] = useState<Record<string, DictData[]>>({})
    const [loading, setLoading] = useState(true)
    const [error, setError] = useState<string | null>(null)

    const loadDictData = useCallback(async () => {
        if (dictTypes.length === 0) {
            setLoading(false)
            return
        }

        try {
            setLoading(true)
            setError(null)
            
            // 检查哪些字典已经加载
            const loadedData: Record<string, DictData[]> = {}
            const pendingTypes: string[] = []

            for (const dictType of dictTypes) {
                if (dictManager.isDictLoaded(dictType)) {
                    loadedData[dictType] = await dictManager.getDictData(dictType)
                } else {
                    pendingTypes.push(dictType)
                }
            }

            // 如果有已加载的数据，立即显示
            if (Object.keys(loadedData).length > 0) {
                setDictData(prev => ({ ...prev, ...loadedData }))
                
                // 如果所有数据都已加载，结束loading状态
                if (pendingTypes.length === 0) {
                    setLoading(false)
                    return
                }
            }

            // 加载剩余的数据
            if (pendingTypes.length > 0) {
                const remainingData = await dictManager.getMultipleDictData(pendingTypes)
                setDictData(prev => ({ ...prev, ...remainingData }))
            }

        } catch (err) {
            console.error('加载字典数据失败:', err)
            setError(err instanceof Error ? err.message : '加载字典数据失败')
        } finally {
            setLoading(false)
        }
    }, [dictTypes])

    useEffect(() => {
        loadDictData()
    }, [loadDictData])

    // 使用useMemo缓存字典选项，避免每次渲染都重新计算
    const dictOptionsCache = useMemo(() => {
        const cache: Record<string, Array<{ label: string; value: string | number }>> = {}
        dictTypes.forEach(dictType => {
            const data = dictData[dictType]
            if (Array.isArray(data)) {
                cache[dictType] = data.map(item => ({
                    label: item.label,
                    value: item.value
                }))
            } else {
                cache[dictType] = []
            }
        })
        return cache
    }, [dictData, dictTypes])

    // 使用useCallback确保函数引用稳定
    const getDictOptions = useCallback((dictType: string) => {
        return dictOptionsCache[dictType] || []
    }, [dictOptionsCache])

    const getDictLabel = useCallback((dictType: string, value: string | number) => {
        // 优先使用缓存的数据
        if (dictData[dictType]) {
            const options = dictOptionsCache[dictType]
            if (Array.isArray(options)) {
                let item = options.find(d => d.value === value)
                if (!item) {
                    item = options.find(d => String(d.value) === String(value))
                }
                if (!item) {
                    item = options.find(d => Number(d.value) === Number(value))
                }
                if (item) {
                    return item.label
                }
            }
        }
        
        return dictManager.getDictLabel(dictType, value)
    }, [dictData, dictOptionsCache])

    const getIntDictOptions = useCallback((dictType: string) => {
        const options = dictOptionsCache[dictType]
        if (!Array.isArray(options)) {
            return []
        }
        return options.map(item => ({
            label: item.label,
            value: parseInt(String(item.value), 10)
        }))
    }, [dictOptionsCache])

    const getStrDictOptions = useCallback((dictType: string) => {
        const options = dictOptionsCache[dictType]
        if (!Array.isArray(options)) {
            return []
        }
        return options.map(item => ({
            label: item.label,
            value: String(item.value)
        }))
    }, [dictOptionsCache])

    const refresh = useCallback(async () => {
        // 清除指定字典类型的缓存并重新加载
        for (const dictType of dictTypes) {
            await dictManager.refreshDictType(dictType)
        }
        await loadDictData()
    }, [dictTypes, loadDictData])

    return useMemo(() => ({
        dictData,
        loading,
        error,
        refresh,
        getDictOptions,
        getDictLabel,
        getIntDictOptions,
        getStrDictOptions
    }), [
        dictData,
        loading,
        error,
        refresh,
        getDictOptions,
        getDictLabel,
        getIntDictOptions,
        getStrDictOptions
    ])
}

/**
 * 单个字典类型Hook
 */
export const useSingleDict = (dictType: string) => {
    const { dictData, loading, error, refresh, getDictOptions, getDictLabel } = useDict([dictType])
    
    return {
        data: dictData[dictType] || [],
        options: getDictOptions(dictType),
        loading,
        error,
        refresh,
        getLabel: (value: string | number) => getDictLabel(dictType, value)
    }
}

/**
 * 优化的请假相关字典Hook - 使用全局字典管理器
 * 只会在第一次调用时加载，后续直接从缓存获取
 */
export const useLeaveDict = () => {
    const [dictData, setDictData] = useState<Record<string, DictData[]>>({})
    const [loading, setLoading] = useState(false)
    const [error, setError] = useState<string | null>(null)

    const leaveTypes = useMemo(() => [
        DICT_TYPE.LEAVE_TYPE,
        DICT_TYPE.PERSONAL_TYPE,
        DICT_TYPE.ACADEMIC_NATURE,
        DICT_TYPE.PERSONAL_VISIT_TYPE,
        DICT_TYPE.MARITAL_STATUS,
        DICT_TYPE.PARITY,
        DICT_TYPE.IS_PRESENTATION,
        DICT_TYPE.REPORT_TYPE,
        DICT_TYPE.IS_MULTIPLE_BIRTH,
        DICT_TYPE.IS_DYSTOCIA
    ], [])

    const loadData = useCallback(async () => {
        try {
            // 检查是否所有字典都已加载
            const allLoaded = leaveTypes.every(type => dictManager.isDictLoaded(type))
            
            if (allLoaded) {
                // 如果都已加载，直接从管理器获取
                const data: Record<string, DictData[]> = {}
                for (const type of leaveTypes) {
                    data[type] = await dictManager.getDictData(type)
                }
                setDictData(data)
                return
            }

            // 否则显示加载状态并加载未缓存的数据
            setLoading(true)
            setError(null)
            
            const data = await dictManager.getMultipleDictData(leaveTypes)
            setDictData(data)
        } catch (err) {
            setError(err instanceof Error ? err.message : '加载字典数据失败')
        } finally {
            setLoading(false)
        }
    }, [leaveTypes])

    useEffect(() => {
        loadData()
    }, [loadData])

    const getDictOptions = useCallback((dictType: string) => {
        const data = dictData[dictType] || []
        return data.map(item => ({ label: item.label, value: item.value }))
    }, [dictData])

    const getDictLabel = useCallback((dictType: string, value: string | number) => {
        const options = getDictOptions(dictType)
        let item = options.find(d => d.value === value)
        if (!item) item = options.find(d => String(d.value) === String(value))
        if (!item) item = options.find(d => Number(d.value) === Number(value))
        return item?.label || String(value)
    }, [getDictOptions])

    const getIntDictOptions = useCallback((dictType: string) => {
        return getDictOptions(dictType).map(item => ({
            label: item.label,
            value: parseInt(String(item.value), 10)
        }))
    }, [getDictOptions])

    const getStrDictOptions = useCallback((dictType: string) => {
        return getDictOptions(dictType).map(item => ({
            label: item.label,
            value: String(item.value)
        }))
    }, [getDictOptions])

    const refresh = useCallback(async () => {
        for (const type of leaveTypes) {
            await dictManager.refreshDictType(type)
        }
        await loadData()
    }, [leaveTypes, loadData])

    return {
        dictData,
        loading,
        error,
        refresh,
        getDictOptions,
        getDictLabel,
        getIntDictOptions,
        getStrDictOptions
    }
}